%%%-------------------------------------------------------------------
%%% @author Rain
%%% @copyright (C) 2022, <COMPANY>
%%% @doc
%%% @end
%%%-------------------------------------------------------------------
-module(uid_svr).

-behaviour(gen_server).
-include("tower_aoi.hrl").

-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
    code_change/3, start_uid_svr/0, set_uid_route_pid/2]).

-export([account_uid/1, get_uid_route_pid/1]).

-define(SERVER, ?MODULE).

-record(uid_svr_state, {}).

%%%===================================================================
%%% Spawning and gen_server implementation
%%%===================================================================

start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
    ets:new(?ETS_UID, [public, set, named_table, {keypos, 1}, {read_concurrency, true}]),
    {ok, #uid_svr_state{}}.

handle_call(_Request, _From, State = #uid_svr_state{}) ->
    {reply, ok, State}.

handle_cast(_Request, State = #uid_svr_state{}) ->
    {noreply, State}.

handle_info(_Info, State = #uid_svr_state{}) ->
    {noreply, State}.

terminate(_Reason, _State = #uid_svr_state{}) ->
    ok.

code_change(_OldVsn, State = #uid_svr_state{}, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================

start_uid_svr() ->
    ChildSpec = #{id => ?MODULE,
        start => {?MODULE, start_link, []},
        restart => permanent,
        shutdown => 2000,
        type => worker,
        modules => [?MODULE]},
    supervisor:start_child(tower_aoi_server_sup, ChildSpec).

account_uid(AccountName) ->
    case ets:lookup(?ETS_UID, {account_name, AccountName}) of
        [{_, UidValue}|_] when is_integer(UidValue) ->
            UidValue;
        _ ->
            get_new_uid(AccountName)
    end.

get_base_uid() ->
    10000.

get_new_uid(AccountName) ->
    MaxUid = get_max_uid(),
    MaxUid1 = MaxUid + 1,
    ets:insert(?ETS_UID, {max_uid, MaxUid1}),
    ets:insert(?ETS_UID, {{account_name, AccountName}, MaxUid}),
    MaxUid.

get_max_uid() ->
    case ets:lookup(?ETS_UID, max_uid) of
        [{_, Value}|_] when is_integer(Value) ->
            Value;
        _ ->
            get_base_uid()
    end.

get_uid_route_pid(UidValue) ->
    case ets:lookup(?ETS_UID, {route_pid, UidValue}) of
        [{_, Pid}|_] when is_pid(Pid) ->
            Pid;
        _ ->
            undefined
    end.

set_uid_route_pid(UidValue, Pid) ->
    ets:insert(?ETS_UID, {{route_pid, UidValue}, Pid}).